#include "common.h"
#include "object.h"
#include <cstdio>
#include <boost/thread.hpp>
#include "Engine.h"


std::list<object*> olist;

boost::mutex gmemory_mutex;


double dotm(v3d &one, v3d &two) ///dot multiplication, which ALSO takes the magnitude of the results. Hence, dotM not dot
{

    v3d ret;
    ret.x=one.x*two.x;
    ret.y=one.y*two.y;
    ret.z=one.z*two.z;


    return ((ret.x+ret.y+ret.z)/sqrt((one.x*one.x+one.y*one.y+one.z*one.z)*(two.x*two.x+two.y*two.y+two.z*two.z)));


}

v3d crossm(v3d &one, v3d &two) ///cross multiplication. The M is there simply because i am incompetent
{



    v3d ret;

    ret.x=one.y*two.z - one.z*two.y;
    ret.y=one.z*two.x - one.x*two.z;
    ret.z=one.x*two.y - one.y*two.x;

    return ret;



}


object *spawn_object(triangle *tris, int num) ///push to global object manager
{

    object *T=new object;

    T->position(0,0,0);

    T->allocate_triangles(num);

    for(int i=0; i<num; i++)
    {
        T->add_triangle(tris[i]);
    }

    T->push();
    return T;


}


object *parse_obj(std::string filename, std::string extension)
{

    FILE *pFile=fopen(filename.c_str(), "r");

    if(pFile==NULL)
    {
        exit(1112);
    }


    std::list<v3d> vlist;

    int length=0; ///including newlines
    int lines=0;

    int maxlinelength=0;
    int temp=0;
    int normals=0;


    while(!feof(pFile))
    {

        length++;
        if(fgetc(pFile)=='\n')
        {
            lines++;
            if(length-temp>maxlinelength)
            {
                maxlinelength=length-temp;
            }
            temp=length;

        }


    }

    rewind(pFile);


    int vnum=0;

    char **arr=new char*[lines];




    for(int i=0; i<lines; i++)
    {
        i[arr]=new char[maxlinelength];
        for(int j=0; j<maxlinelength; j++)
        {
            j[i[arr]]='\0';


        }
    }

    for(int i=0; i<lines; i++)
    {
        for(int j=0; j<maxlinelength; j++)
        {
            arr[i][j]=fgetc(pFile);
            if(arr[i][j]=='\n')
            {
                break;
            }
        }
    }



    fclose(pFile);

    int facenum=0;

    int vtnum=0;

    for(int i=0; i<lines; i++)
    {
        for(int j=0; j<maxlinelength; j++)
        {


            if(arr[i][j]=='v'&& j==0 && arr[i][j+1]==' ')
            {
                vnum++;
            }
            if(arr[i][j]=='v' && j==0 && arr[i][j+1]=='n' && arr[i][j+2]==' ')
            {
                normals++;
            }
            if(arr[i][j]=='f' && j==0 && arr[i][j+1]==' ')
            {
                facenum++;
            }
            if(arr[i][j]=='v' && j==0 && arr[i][j+1]=='t' && arr[i][j+2]==' ')
            {
                vtnum++;
            }

        }

    }

    v3d *v=new v3d[vnum];

    int cur=0;

    int cvnum=0;

    double x=0, y=0, z=0;


    for(int i=0; i<lines; i++)
    {
        ///need to do -1 check so not out of bounds, but nvm for now
        if(arr[i][0]=='v' && arr[i][1]==' ')
        {



            for(int j=0; j<maxlinelength; j++)
            {

                if(arr[i][j]!='\0')
                {

                }
                else
                {
                    break;
                }

                if(arr[i][j]==' ')
                {



                    if(cur==2)
                    {
                        z=atof(&arr[i][j]);
                        cur++;
                    }

                    if(cur==1)
                    {
                        y=atof(&arr[i][j]);
                        cur++;
                    }

                    if(cur==0)
                    {
                        x=atof(&arr[i][j]);
                        cur++;
                    }




                }

                if(cur>2)
                {
                    v[cvnum](x, y, z);
                    cvnum++;
                    cur=0;
                    break;
                }



            }

        }



    }
    cur=0;

    object *obj=new object;

    obj->allocate_triangles(facenum);

    obj->gid_take();


    vertex vert;

    sf::Color c(255,255,255);



    cur=0;

    v3d *anormal=new v3d[normals];
    v3d *vtexc=new v3d[vtnum];
    int anormalc=0;

    int vtexcc=0;




    for(int i=0; i<lines; i++)
    {

        if(strncmp("usemtl", arr[i], strlen("usemtl"))==0)
        {

            int len=strlen("usemtl");
            len++;

            char *temp=new char[maxlinelength+100];

            int tc=0;

            while(tc!=' ' && tc!='\n')
            {
                tc=arr[i][len];
                temp[len-(strlen("usemtl")+1)]= ((tc == '\n') || (tc == ' ')) ? '\0' : tc;
                len++;
            }

            //obj->texname=temp;
            strcat(temp, extension.c_str()); ///archaic
            obj->texname=temp;
            //obj->texname=std::string(temp);// + std::string(".bmp");
            delete [] temp;

        }

        if(arr[i][0]=='v' && arr[i][1]=='n' && arr[i][2]==' ')
        {

            for(int j=0; j<maxlinelength; j++)
            {


                if(arr[i][j]=='\0')
                {
                    break;
                }


                if(arr[i][j]==' '&& cur<3)
                {

                    if(cur==2)
                    {
                        z=atof(&arr[i][j]);
                        cur++;
                    }
                    if(cur==1)
                    {
                        y=atof(&arr[i][j]);
                        cur++;
                    }
                    if(cur==0)
                    {
                        x=atof(&arr[i][j]);
                        cur++;
                    }

                }


                if(cur>2)
                {

                    anormal[anormalc](x,y,z);
                    anormalc++;
                    cur=0;
                    break;

                }



            }


        }



    }



    for(int i=0; i<lines; i++)
    {

        if(arr[i][0]=='v' && arr[i][1]=='t' && arr[i][2]==' ')
        {

            for(int j=0; j<maxlinelength; j++)
            {


                if(arr[i][j]=='\0')
                {
                    break;
                }


                if(arr[i][j]==' '&& cur<2)
                {


                    if(cur==1)
                    {
                        y=atof(&arr[i][j]);
                        cur++;
                    }
                    if(cur==0)
                    {
                        x=atof(&arr[i][j]);
                        cur++;
                    }

                }


                if(cur>1)
                {

                    vtexc[vtexcc](x,y,obj->gid);
                    vtexcc++;
                    cur=0;
                    break;

                }



            }


        }



    }


    v3d normal[3];

    cur=0;

    v3d vtt[3];

    ///dont forget usemtl


    for(int i=0; i<lines; i++)
    {
        if(arr[i][0]=='f' && arr[i][0+1]==' ')
        {
            triangle n;

            int slashcount=0;
            int as=0;


            for(int j=0; j<maxlinelength; j++)
            {

                if(arr[i][j]=='\0')
                {
                    break;
                }

                if(arr[i][j]=='/')
                {
                    slashcount++;

                }

                if(arr[i][j]=='/' && ((slashcount + 1)%2)==0)
                {
                    as=atoi(&arr[i][j+1]);

                    vtt[cur]=vtexc[as-1];

                }

                if(j>3 && arr[i][j]=='/' && (slashcount % 2) == 0)
                {

                    as=atoi(&arr[i][j+1]);

                    normal[cur]=anormal[as-1];

                    cur++;

                }


                if(arr[i][j]==' '&& cur<3) ///reach new face, add old face to vertex. But apparently not the normal, for some strange reason
                {

                    int p=atoi(&arr[i][j]);

                    vert(v[p-1], c);

                    n.add_point(vert);

                }

                if(cur>2)
                {

                    for(int ar=0; ar<3; ar++)
                    {
                        n.points[ar].add_normal(normal[ar]);
                        n.points[ar].add_uvw(vtt[ar]);
                    }

                    obj->add_triangle(n);

                    cur=0;
                    break;


                }
            }
        }
    }

    delete [] v;

    for(int i=0; i<lines; i++)
    {
        delete [] arr[i];

    }

    delete [] arr;

    delete [] anormal;
    delete [] vtexc;



    return obj;


}

